/**
 * 
 */
package com.dalonedrow.module.hq.ui.widgets;

import com.dalonedrow.engine.sprite.base.SpriteImageObjectFactory;
import com.dalonedrow.engine.systems.JOGLErrorHandler;
import com.dalonedrow.engine.systems.base.Action;
import com.dalonedrow.engine.systems.base.InputEvent;
import com.dalonedrow.engine.systems.base.Interactive;
import com.dalonedrow.engine.systems.base.Interface;
import com.dalonedrow.engine.systems.base.ProjectConstants;
import com.dalonedrow.engine.ui.base.panel.LandscapePagePanel;
import com.dalonedrow.engine.ui.base.panel.Panel;
import com.dalonedrow.engine.ui.base.panel.PortraitPagePanel;
import com.dalonedrow.engine.ui.impl.Button;
import com.dalonedrow.engine.ui.impl.UIFactory;
import com.dalonedrow.globalvariables.constants.hq.GlobalConstants;
import com.dalonedrow.module.hq.rpg.HQInteractiveObject;
import com.dalonedrow.module.hq.rpg.HQTerrainTypes;
import com.dalonedrow.module.hq.systems.HQMap;
import com.dalonedrow.module.hq.systems.HQMovement;
import com.dalonedrow.module.hq.systems.HQScript;
import com.dalonedrow.module.hq.systems.HQTurn;
import com.dalonedrow.module.hq.ui.views.DungeonScreenView;
import com.dalonedrow.pooled.PooledStringBuilder;
import com.dalonedrow.pooled.StringBuilderPool;

/**
 * @author Donald
 */
public final class HQActionMenu extends PortraitPagePanel {
	/** the singleton instance of {@link HQActionMenu}. */
	private static HQActionMenu	instance;
	/**
	 * Gets the singleton instance of {@link HQActionMenu}.
	 * @return {@link HQActionMenu}
	 */
	public static HQActionMenu getInstance() {
		if (HQActionMenu.instance == null) {
			HQActionMenu.instance = new HQActionMenu();
		}
		return HQActionMenu.instance;
	}
	/** the action taken flag. Only one action is allowed per turn. */
	private long		actionTaken	= 0L;
	/** the list of action buttons. */
	private Button[]	buttons;
	/**
	 * Creates a new instance of {@link HQActionMenu}.
	 */
	private HQActionMenu() {
		super(Panel.PORTRAIT_CENTER);
		try {
			init();
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	public void castSpell() {

	}
	/** Ends the player's turn. */
	public void endTurn() {
		try {
			HQInteractiveObject pc =
					(HQInteractiveObject) Interactive.getInstance().getIO(
							ProjectConstants.getInstance().getPcId());
			// does the player have moves left?
			int m = pc.getScript().getLocalVariable("movesLeft").getIntVal();
			if (m > 0) {
				// player has moves left. ask if wants to end turn
				Interface.getInstance().showSmallOptionsMessageWindow(
						"End Turn?",
						"Do You want to end your turn?  You will not be able "
								+ "to move again until the next turn.",
						new Action() {
							/**
							 * {@inheritDoc}
							 */
							@Override
							public void performAction() {
								try {
									Interface.getInstance()
											.hideSmallOptionsMessageWindow();
									HQTurn.getInstance().nextIOTurnCycle();
								} catch (Exception ex) {
									JOGLErrorHandler.getInstance().fatalError(
											ex);
								}
							}
						});
			} else if (actionTaken == 0) {
				// player has moves left. ask if wants to end turn
				Interface.getInstance().showSmallOptionsMessageWindow(
						"End Turn?",
						"Do You want to end your turn?  You will not be able "
								+ "to take any actions until the next turn.",
						new Action() {
							/**
							 * {@inheritDoc}
							 */
							@Override
							public void performAction() {
								try {
									Interface.getInstance()
											.hideSmallOptionsMessageWindow();
									HQTurn.getInstance().nextIOTurnCycle();
								} catch (Exception ex) {
									JOGLErrorHandler.getInstance().fatalError(
											ex);
								}
							}
						});
			} else {
				HQTurn.getInstance().nextIOTurnCycle();
			}
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void handleMouseOver(final float x, final float y) {
		if (super.contains(x, y)) {
			for (int i = 0; i < buttons.length; i++) {
				if (buttons[i].contains(x, y)) {
					ProjectConstants.getInstance().setCursor(
							GlobalConstants.CURSOR_12_HAND);
					switch (i) {
					case 0:
						if (buttons[i].isActive()) {
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Cast a Spell");
						} else {
							ProjectConstants.getInstance().setCursor(
									GlobalConstants.CURSOR_00_DEFAULT);
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Cannot use magic");
						}
						break;
					case 1:
						if (buttons[i].isActive()) {
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Search for treasure");
						} else {
							ProjectConstants.getInstance().setCursor(
									GlobalConstants.CURSOR_00_DEFAULT);
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Cannot search here");
						}
						break;
					case 2:
						if (buttons[i].isActive()) {
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Search for secret doors");
						} else {
							ProjectConstants.getInstance().setCursor(
									GlobalConstants.CURSOR_00_DEFAULT);
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Cannot search here");
						}
						break;
					case GlobalConstants.INT_003:
						if (buttons[i].isActive()) {
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Search for traps");
						} else {
							ProjectConstants.getInstance().setCursor(
									GlobalConstants.CURSOR_00_DEFAULT);
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Cannot search here");
						}
						break;
					case GlobalConstants.INT_004:
						if (buttons[i].isActive()) {
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"Disarm trap");
						} else {
							ProjectConstants.getInstance().setCursor(
									GlobalConstants.CURSOR_00_DEFAULT);
							DungeonScreenView.getInstance()
									.updateActionMessage(
											"No Traps to Disarm");
						}
						break;
					case GlobalConstants.INT_005:
						DungeonScreenView.getInstance().updateActionMessage(
								"End your turn");
						break;
					}
					break;
				}
			}
		} else {
			ProjectConstants.getInstance().setCursor(
					GlobalConstants.CURSOR_00_DEFAULT);
		}
	}
	/**
	 * Initializes the viewer.
	 * @throws Exception if an error occurs
	 */
	private void init() throws Exception {
		buttons = new Button[GlobalConstants.INT_006];
		int c = 0;
		// 1st row - Cast, Treasure, Door
		Panel top = new LandscapePagePanel(Panel.LANDSCAPE_CENTER);
		int imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_cast");
		buttons[c] = UIFactory.getInstance().getStandardImageButton(imgRef);
		buttons[c].addAction(new Action() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public void performAction() {
				try {
					// cast spell
					InputEvent.getInstance().addAction(
							HQActionMenu.getInstance(), // object
							HQActionMenu.class.getMethod(
									"castSpell", (Class<?>[]) null),
							null
							);
				} catch (Exception ex) {
					JOGLErrorHandler.getInstance().fatalError(ex);
				}
			}
		});
		top.addChild(buttons[c]);
		c++;
		imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_sear_treas");
		buttons[c] = UIFactory.getInstance().getStandardImageButton(imgRef);
		buttons[c].addAction(new Action() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public void performAction() {
				try {
					// search for treasure
					InputEvent.getInstance().addAction(
							HQActionMenu.getInstance(), // object
							HQActionMenu.class.getMethod(
									"searchForTreasure", (Class<?>[]) null),
							null
							);
				} catch (Exception ex) {
					JOGLErrorHandler.getInstance().fatalError(ex);
				}
			}
		});
		top.addChild(buttons[c]);
		c++;
		imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_sear_door");
		buttons[c] = UIFactory.getInstance().getStandardImageButton(imgRef);
		buttons[c].addAction(new Action() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public void performAction() {
				try {
					// cast spell
					InputEvent.getInstance().addAction(
							HQActionMenu.getInstance(), // object
							HQActionMenu.class.getMethod(
									"searchForDoor", (Class<?>[]) null),
							null
							);
				} catch (Exception ex) {
					JOGLErrorHandler.getInstance().fatalError(ex);
				}
			}
		});
		top.addChild(buttons[c]);
		c++;
		imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_sear_trap");
		buttons[c] = UIFactory.getInstance().getStandardImageButton(imgRef);
		buttons[c].addAction(new Action() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public void performAction() {
				try {
					// cast spell
					InputEvent.getInstance().addAction(
							HQActionMenu.getInstance(), // object
							HQActionMenu.class.getMethod(
									"searchForTraps", (Class<?>[]) null),
							null
							);
				} catch (Exception ex) {
					JOGLErrorHandler.getInstance().fatalError(ex);
				}
			}
		});
		top.addChild(buttons[c]);
		c++;
		imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_disarm_trap");
		buttons[c] = UIFactory.getInstance().getStandardImageButton(imgRef);
		buttons[c].addAction(new Action() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public void performAction() {
				try {
					// cast spell
					InputEvent.getInstance().addAction(
							HQActionMenu.getInstance(), // object
							HQActionMenu.class.getMethod(
									"disarmTrap", (Class<?>[]) null),
							null
							);
				} catch (Exception ex) {
					JOGLErrorHandler.getInstance().fatalError(ex);
				}
			}
		});
		top.addChild(buttons[c]);
		c++;
		imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_cancel");
		buttons[c] = UIFactory.getInstance().getStandardImageButton(imgRef);
		buttons[c].addAction(new Action() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public void performAction() {
				try {
					// cast spell
					InputEvent.getInstance().addAction(
							HQActionMenu.getInstance(), // object
							HQActionMenu.class.getMethod(
									"endTurn", (Class<?>[]) null),
							null
							);
				} catch (Exception ex) {
					JOGLErrorHandler.getInstance().fatalError(ex);
				}
			}
		});
		top.addChild(buttons[c]);
		super.addChild(top);
	}
	/**
	 * Determines if the PC can search a room for secret doors. Rooms can only
	 * be searched once, and the PC cannot search for doors while standing in a
	 * doorway.
	 * @param pc the pc instance
	 * @return true if the PC is in a room that hasn't been searched, and is not
	 *         in a doorway
	 * @throws Exception if an error occurs
	 */
	private boolean pcCanSearchForDoor(final HQInteractiveObject pc)
			throws Exception {
		boolean can = true;
		if (HQMap.getInstance().getTerrainIOIsOn(pc.getRefId())
				!= HQTerrainTypes.getInstance().getTerrainId(
				"ultima_floor_to_wall")) {
			can = false;
		}
		if (can) {
			int[] rooms = HQMap.getInstance().getRoomsForIO(pc.getRefId());
			PooledStringBuilder sb =
					StringBuilderPool.getInstance()
							.getStringBuilder();
			sb.append(HQScript.getInstance()
					.getGlobalStringVariableValue(
							"currentMapName"));
			sb.append("_roomsDoorSearched");
			int[] visited = null;
			try {
				visited = HQScript.getInstance()
						.getGlobalIntArrayVariableValue(
								sb.toString());
			} catch (Exception ex) {
				visited = new int[0];
				HQScript.getInstance()
						.setGlobalVariable(sb.toString(), visited);
			}
			sb.returnToPool();
			for (int outer = 0; outer < rooms.length; outer++) {
				for (int inner = 0; inner < visited.length; inner++) {
					if (rooms[outer] == visited[inner]) {
						can = false;
						break;
					}
				}
			}
		}
		return can;
	}
	/**
	 * Determines if the PC can search a room for treasure. Rooms can only be
	 * searched once, and the PC cannot search for doors while standing in a
	 * doorway.
	 * @param pc the pc instance
	 * @return true if the PC is in a room that hasn't been searched, and is not
	 *         in a doorway
	 * @throws Exception if an error occurs
	 */
	private boolean pcCanSearchForTreasure(final HQInteractiveObject pc)
			throws Exception {
		System.out.println("****pcCanSearchForTreasure(");
		boolean can = true;
		if (HQMap.getInstance().isRoomIOIsInACorridor(pc.getRefId())) {
			// no searching allowed in corridors
			can = false;
		}
		if (can) {
			System.out.println("in a room");
			int[] rooms = HQMap.getInstance().getRoomsForIO(pc.getRefId());
			PooledStringBuilder sb =
					StringBuilderPool.getInstance()
							.getStringBuilder();
			sb.append(HQScript.getInstance()
					.getGlobalStringVariableValue(
							"currentMapName"));
			sb.append("_roomsTreasureSearched");
			int[] visited = null;
			try {
				visited = HQScript.getInstance()
						.getGlobalIntArrayVariableValue(
								sb.toString());
			} catch (Exception ex) {
				System.out.println("caught exception, creating visited array");
				visited = new int[0];
				HQScript.getInstance()
						.setGlobalVariable(sb.toString(), visited);
			}
			sb.returnToPool();
			for (int outer = 0; outer < rooms.length; outer++) {
				for (int inner = 0; inner < visited.length; inner++) {
					if (rooms[outer] == visited[inner]) {
						System.out.println("room has been searched already");
						can = false;
						break;
					}
				}
			}
			if (can) {
				System.out.println("check for hostile ios");
				int[] ios = HQMap.getInstance().getIOsInRoom(rooms[0]);
				for (int i = 0; i < ios.length; i++) {
					// check to see if any hostile creatures are in the room
					HQInteractiveObject io =
							(HQInteractiveObject) Interactive.getInstance()
									.getIO(
											ios[i]);
					if (ios[i] == ProjectConstants.getInstance().getPcId()) {
						// skip the PC
						continue;
					}
					if (io.hasIOFlag(GlobalConstants.IO_03_NPC)
							&& io.getScript().getLocalIntVariableValue("enemy") > 0) {
						System.out.println("hostile IO!");
						can = false;
						break;
					}
				}
			}
		}
		return can;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void prepareForRendering() throws Exception {
		// check to see if cast button needs to be disabled
		HQInteractiveObject pc =
				(HQInteractiveObject) Interactive.getInstance().getIO(
						ProjectConstants.getInstance().getPcId());
		int imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_cast_disabled");
		buttons[0].setActive(false);
		if (actionTaken == 0L
				&& pc.getPCData().canCastSpells()) {
			imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
					"hq_btn_act_cast");
			buttons[0].setActive(true);
		}
		buttons[0].getSprite().setImageRefId(imgRef);
		// check to see if treasure button needs to be disabled
		buttons[1].setActive(false);
		imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_sear_treas_disabled");
		if (actionTaken == 0L
				&& pcCanSearchForTreasure(pc)) {
			imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
					"hq_btn_act_sear_treas");
			buttons[1].setActive(true);
		}
		buttons[1].getSprite().setImageRefId(imgRef);
		// check to see if can search for doors
		if (actionTaken == 0L
				&& pcCanSearchForDoor(pc)) {
			imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
					"hq_btn_act_sear_door");
			buttons[2].setActive(true);
		}
		buttons[2].getSprite().setImageRefId(imgRef);
		// check to see if door button needs to be disabled
		imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_sear_door_disabled");
		buttons[2].setActive(false);
		if (actionTaken == 0L
				&& pcCanSearchForDoor(pc)) {
			imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
					"hq_btn_act_sear_door");
			buttons[2].setActive(true);
		}
		buttons[2].getSprite().setImageRefId(imgRef);
		// check to see if disarm traps button needs to be disabled
		imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
				"hq_btn_act_disarm_trap_disabled");
		buttons[GlobalConstants.INT_004].setActive(false);
		if (actionTaken == 0L
				&& pc.getPCData().canCastSpells()) {
			imgRef = SpriteImageObjectFactory.getInstance().getImageRefId(
					"hq_btn_act_disarm_trap");
			buttons[GlobalConstants.INT_004].setActive(true);
		}
		buttons[GlobalConstants.INT_004].getSprite().setImageRefId(imgRef);
		super.prepareForRendering();
	}
	/** Resets the action taken flag. Only one action is allowed per turn. */
	public void resetActionTaken() {
		actionTaken = 0L;
	}
	/** Handles actions when the player clicks the "Search for doors" button. */
	public void searchForDoor() {
		try {
			final HQInteractiveObject pc =
					(HQInteractiveObject) ProjectConstants.getInstance()
							.getPCObject();
			// does the player have moves left?
			int ml = pc.getScript().getLocalVariable("movesLeft").getIntVal();
			int mm = pc.getScript().getLocalVariable("movesMaxInTurn")
					.getIntVal();
			if (ml == 0
					|| ml > 0 && ml < mm) {
				// player has some moves left
				// - OR -
				// player has no moves left
				// turn should end after search
				Interface.getInstance().showSmallOptionsMessageWindow(
						"Search For Secret Doors?",
						"If you search now, your turn will end after the "
								+ "search is completed.",
						new Action() {
							/**
							 * {@inheritDoc}
							 */
							@Override
							public void performAction() {
								try {
									PooledStringBuilder sb =
											StringBuilderPool.getInstance()
													.getStringBuilder();
									HQInteractiveObject hio = (HQInteractiveObject) ProjectConstants
											.getInstance()
											.getPCObject();
									sb.append(hio.getPCData().getName());
									hio = null;
									sb.append(" searches for secret doors.\n");
									DungeonScreenView.getInstance()
											.sendPlayerMessage(sb.toString());
									sb.returnToPool();
									Interface.getInstance()
											.hideSmallOptionsMessageWindow();
									HQMap.getInstance().findSecretDoorsInRoom(
											pc.getRefId(), true);
								} catch (Exception ex) {
									JOGLErrorHandler.getInstance().fatalError(
											ex);
								}
							}
						});
			} else if (ml == mm) {
				// player has all moves left. ask if wants to end turn
				Interface.getInstance().showSmallOptionsMessageWindow(
						"Search For Secret Doors?",
						"Do You want to search for secret doors?  You "
								+ "will not be able to take any "
								+ "further actions beyond movement "
								+ "until the next turn.",
						new Action() {
							/**
							 * {@inheritDoc}
							 */
							@Override
							public void performAction() {
								try {
									actionTaken = 4;
									PooledStringBuilder sb =
											StringBuilderPool.getInstance()
													.getStringBuilder();
									HQInteractiveObject hio = (HQInteractiveObject) ProjectConstants
											.getInstance()
											.getPCObject();
									sb.append(hio.getPCData().getName());
									hio = null;
									sb.append(" searches for secret doors.\n");
									DungeonScreenView.getInstance()
											.sendPlayerMessage(sb.toString());
									sb.returnToPool();
									Interface
											.getInstance()
											.hideSmallOptionsMessageWindow();
									HQMap.getInstance()
											.findSecretDoorsInRoom(
													pc.getRefId(), false);
								} catch (Exception ex) {
									JOGLErrorHandler.getInstance()
											.fatalError(
													ex);
								}
							}
						});
			}
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	/** Handles actions when the player clicks the "Search for doors" button. */
	public void searchForTreasure() {
		try {
			if (shouldTurnEndAfterAction()) {
				Interface.getInstance().showSmallOptionsMessageWindow(
						"Search For Treasure?",
						"If you search now, your turn will end after the "
								+ "search is completed.",
						new Action() {
							/**
							 * {@inheritDoc}
							 */
							@Override
							public void performAction() {
								try {
									PooledStringBuilder sb =
											StringBuilderPool.getInstance()
													.getStringBuilder();
									HQInteractiveObject hio = (HQInteractiveObject) ProjectConstants
											.getInstance()
											.getPCObject();
									sb.append(hio.getPCData().getName());
									hio = null;
									sb.append(" searches for treasure.\n");
									DungeonScreenView.getInstance()
											.sendPlayerMessage(sb.toString());
									sb.returnToPool();
									Interface.getInstance()
											.hideSmallOptionsMessageWindow();
									HQMovement.getInstance().startSearch(
											ProjectConstants.getInstance()
													.getPcId(), true);
								} catch (Exception ex) {
									JOGLErrorHandler.getInstance().fatalError(
											ex);
								}
							}
						});
			} else {

				Interface.getInstance().showSmallOptionsMessageWindow(
						"Search For Treasure?",
						"Do You want to search for treasure now?  Afterwards, "
								+ "you will not be able to take any "
								+ "further actions except movement "
								+ "until the next turn.",
						new Action() {
							/**
							 * {@inheritDoc}
							 */
							@Override
							public void performAction() {
								try {
									PooledStringBuilder sb =
											StringBuilderPool.getInstance()
													.getStringBuilder();
									HQInteractiveObject hio = (HQInteractiveObject) ProjectConstants
											.getInstance()
											.getPCObject();
									sb.append(hio.getPCData().getName());
									hio = null;
									sb.append(" searches for treasure.\n");
									DungeonScreenView.getInstance()
											.sendPlayerMessage(sb.toString());
									sb.returnToPool();
									Interface.getInstance()
											.hideSmallOptionsMessageWindow();
									HQMap.getInstance().findTreasureInRoom(
											ProjectConstants.getInstance()
													.getPcId(), true);
								} catch (Exception ex) {
									JOGLErrorHandler.getInstance().fatalError(
											ex);
								}
							}
						});
			}
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	private boolean shouldTurnEndAfterAction() throws Exception {
		boolean should = false;
		HQInteractiveObject pc = (HQInteractiveObject) ProjectConstants
				.getInstance().getPCObject();
		// does the player have moves left?
		int ml = pc.getScript().getLocalIntVariableValue("movesLeft");
		int mm = pc.getScript().getLocalIntVariableValue("movesMaxInTurn");
		if (ml == 0
				|| ml > 0 && ml < mm) {
			// pc used some or all of their moves - end turn after action
			should = true;
		}
		return should;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean touchUp(final int x, final int y,
			final int pointer, final int button) {
		if (super.contains(x, y)) {
			super.touchUp(x, y, pointer, button);
		} else {
			ProjectConstants.getInstance().setCursor(
					GlobalConstants.CURSOR_00_DEFAULT);
		}
		return true;
	}
}
